const { MongoClient, ObjectId } = require("mongodb");
const url = "mongodb://localhost:27017/";
const database = "test"; //test数据库
const options = {
  serverSelectionTimeoutMS: 1000, //多长时间内找不到合适服务器时候就决定放弃的时间间隔
  connectTimeoutMS: 3000, //每次创建Connection 对应的网络等待 单位毫秒数 0表示没有限制
  socketTimeoutMS: 3000, //获取Connection后 就有了Socket通信 获取数据 即在MonogoDB Client 和MonogoDB Server的Socket通信过程中的网络等待时间 单位毫秒数 默认配置为0 也就是没有限制没有超时限制 系统出了问题也不容易发现应该根据实际情况给出合理的超时时间
};
class DB {
  constructor() {}
  getPromiseCollection(collectionName) {
    /*这里我给调用这个方法的实例返回一个自己的Promise 对象
     可通过then 拿到传递的两个值 可通过catch 拿到 传递的错误信息
     */
    return new Promise((resolve, reject) => {
      /*MongoClient.connect(url, options)  方法返回的就是一个promise对象，
      通过then 拿到连接对象，catch 拿到可能出现的链接错误信息*/
      MongoClient.connect(url, options)
        .then((client) =>
          /*promise 只能返回一个参数，我要传递两个参数只能数组传递过去,一个collection对象，一个client 对象
          collection 对象用来操作数据， db对象操作数据完成后关闭连接*/
          resolve([client.db(database).collection(collectionName), client])
        )
        .catch((err) => reject(err));
    });
  }
  /*调用者需传递一个collection 的名字和一个回调数，用回调函数得到这个方法返回的 err或者 collection和client对象
  三个参数  err   collection   client
  */
  getCollection(collectionName, callback) {
    MongoClient.connect(url, options)
      .then(
        (client) =>
          /* 回调函数存在这执行, 第一个参数err 为null  */
          callback &&
          callback(null, client.db(database).collection(collectionName), client)
      )
      .catch((err) => callback && callback(err));
  }
  findById(collectionName, id) {
    return new Promise((resolve, reject) => {
      this.getPromiseCollection(collectionName)
        .then(async (array) => {
          const [collection, client] = array;
          try {
            resolve(await collection.find({ _id: new ObjectId(id) }).toArray());
          } catch (err) {
            reject(err.message);
          } finally {
            client.close();
          }
        })
        .catch((err) => reject(err.message));
    });
  }
}
module.exports = { mongodb: new DB(), ObjectId: ObjectId };
